package com.hfzy.ihk.web.freeswitchCall.support.freeswitch.base;

import com.hfzy.ihk.common.util.string.StringUtil;
import com.hfzy.ihk.common.util.uuid.base64uuid.UUIDs;
import com.hfzy.ihk.facade.aliyuncall.CallRecordBaseEntity;
import com.hfzy.ihk.facade.freeswitchCall.vo.CallHistory;
import com.hfzy.ihk.web.freeswitchCall.constant.Constants;
import com.hfzy.ihk.web.freeswitchCall.support.disruptor.base.DisruptorEvent;
import com.hfzy.ihk.web.freeswitchCall.support.disruptor.base.DisruptorHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by Administrator on 2016/5/26.
 * @author wws
 * 点击拨号业务逻辑抽象类
 * 流程：
 * 1、提交呼叫任务
 * 2、如果提交任务失败，处理它：此处应该用于调用websocket返回状态给客户端浏览器
 * 3、缓存进Map
 */
public abstract class AbstractCallOutHandler<T extends CallRecordBaseEntity,E extends DisruptorEvent<T>> implements DisruptorHandlerAdapter<E> {

    private static final Logger logger = LoggerFactory.getLogger(AbstractCallOutHandler.class);

    /**
     * EventHandler
     */
    @Override
    public void onEvent(E event, long sequence, boolean endOfBatch) throws Exception {
        try {
            procces(event.getData());
        } catch (Exception e) {
            logger.error("AbstactCallOutHandler exception",e);
        }
    }

    /**
     * workHandler
     */
    @Override
    public void onEvent(E event) throws Exception {
        try {
            Long old = System.currentTimeMillis();
            procces(event.getData());
            old = System.currentTimeMillis()-old;
            logger.debug("handle use time:{}",old);

        } catch (Exception e) {
            logger.error("AbstactCallOutHandler exception",e);
        }
    }

    /**
     * 流程方法
     *
     *
     * @param data*/
    protected void procces(T data){
        String result = Constants.SUCCESS;
        //没有sessionId 生成sessionId
        if(StringUtil.isEmpty(data.getSessionId())) {

            try {
                String sessionId = UUIDs.base64UUID();
                if (sessionId == null) {
                    handleIdgeneratedFailed(data);
                    return;
                }
                data.setSessionId(sessionId);
            } catch (Exception e) {//读取redis生产id失败，通知客户端，失败
                handleIdgeneratedFailed(data);
                return;
            }
        }
        //提交给云端
        try {
            logger.debug("{} before commit to fs use sessionId:{}",data.getSessionId());
            Long old = System.currentTimeMillis();
            result= commit(data);
            old = System.currentTimeMillis()-old;
            logger.debug("{} commit to fs use time:{},sessionId:{}",old,data.getSessionId());
        } catch (Exception e) {
            logger.error( "commit failed!",e);
        }


        /*after commit,现在无论提交成功失败都返回给client*/

        try {
            handleAfterCommit(data);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("{} handleAfterCommit failed ! {}",e.getMessage());
        }

        //写入redis
        try {
            writeRedis(data);
            //呼叫失败推送给ES
            if(result.equals(Constants.FAIL)){
                commitFail(data);
            }

        } catch (Exception e) {
            logger.error("writeRedis failed!",e);
            handleWriteRedisFailed(data);
        }



    }




    /**
     * 写redis
     * redis挂了怎么搞？
     * */
    protected abstract String writeRedis(T data);

    /**
     * 注意里面填充好数据
     * @return 成功返回 0,失败返回 -1
     * */
    protected abstract String commit(T data);

    /**
     * 提交失败直接入库
     * @param data
     * @return
     */
    protected abstract String commitFail(T data);

    /**
     * 处理提交呼叫任务失败
     * 调用websocket通知客户端
     * */
    protected abstract void handleAfterCommit(T data);

    /**
     * 生成id失败
     *
     * 由于使用redis生成sessionId,一般是redis挂了
     *
     * */
    protected abstract void handleIdgeneratedFailed(T data);

    /**
     * 处理写redis失败
     * */
    protected abstract String handleWriteRedisFailed(T data);


}
